package com.atguigu.ext;

import com.atguigu.bean.Color;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author gcq
 * @Create 2021-02-08
 *
 * 以下源码都是从AbstractApplicationContext的refresh方法开始
 * 扩展原理
 * BeanPostProcessor:bean后置处理器，bean创建对象初始化前后进行工作
 * BeanFactoryPostProcessor: beanFactory的后置处理器
 *      在BeanFactory标准初始化之后使用，所有的bean定义已经保存加载到beanFactory，但是bean的实例还未创建
 *
 * BeanFactoryPostProcessor原理：
 * 1、ioc容器创建
 * 2、invokeBeanFactoryPostProcessor(beanFactory)
 *      如何找到所有的BeanFactoryPostProcessor并执行它们的方法
 *          1、直接在BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件，并执行他们的方法
 *          2、在初始化创建其他组件前面执行
 * 3、BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
 *      postProcessBeanDefinitionRegistry()
 *      在所有bean定义信息之前加载，bean实例还未创建
 *
 *      优先于BeanFactoryPostProcessor执行
 *      利用BeanDefinitionRegistoryPostProcessor给容器中再添加一些组件
 * 原理：
 *      1、ioc创建对象
 *      2、refresh()-》invokeBeanFactoryPostProcessors(beanFactory)
 *      3、从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件
 *          1、依次触发所有的PostProcessBeanDeinitionRegistry()方法
 *          2、再来触发postProcessBeanFactory()方法BeanFactoryPostProcessor
 *      4、再来从容器中找到BeanFactoryPostProcessor组件，然后依赖触发postProcessBeanFactory()方法
 *
 * 4、ApplicationListener 监听容器中发布的事件，事件驱动模型开发
 *      public interface ApplicationListener<E extends ApplicationEvent> extends EventListener E：泛型必须继承ApplicationContext
 *          监听 ApplicationEvent 及其下面的子事件
 *
 *      步骤:
 *          1、写一个监听器（ApplicationListener实现类）来监听某个时间（ApplicationEvent及其子类）
 *              @EventListener
 *              原理
 *          2、把监听器加入到容器
 *          3、只要容器中有相关事件发布，我们就能监听到这个事件
 *                  ContextRefreshedEvent 容器刷新完成（所有bean都完成创建）会发布这个事件
 *                  ContextCloseEvent 关闭容器会发布这个事件
 *          4、发布一个事件
 *              applicationContext.publishEvent()
 *
 *  原理：
 *      ContextRefreshedEvent、ContextClosedEvent、IOCTest_Ext$1[source=这是一个事件]
 *  1、ContextRefreshEvent事件：
 *      1、容器创建对新啊，refresh()
 *      2、finishRefresh()容器刷新完成会发布ContextRefreshEvent事件
 *  2、自己发布事件
 *  3、容器关闭会发布ContextCloseEvent
 *
 *  【事件发布流程】
 *      3、publishEvent(new ContextRefreshedEvent(this))
 *          1、获取事件的多播器（派发器）getApplicationEventMulticaster()
 *          2、multicastEvent派发事件
 *          3、获取到所有的ApplicationListener
 *              for(final ApplicationListener<?> listener: getApplicationListeners(event, type))
 *              1、如果有Executor 可以支持使用Executor进行异步派发
 *                  Executor executorn = getTaskExecutor()
 *              2、否则，同步的方式直接执行listener方法，invokeListener(listener, event);
 *                  拿到listener回调OnApplicationEvent方法
 *
 * 【事件多播器（派发器）】
 *      1、容器创建对象：refresh();
 *      2、initApplicationEventMulticaste()初始化ApplicationEventMulticaster
 *          1、先去容器中找有没有id = ”applicationEventMulticaster" 的组件
 *          2、如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);【创建】
 *              并且加入到容器中，我们就可以再其他组件要派发事件，自动注入这个applicationEventMulticaster
 *
 * SmartInitializingSingleton 原理 -> afterSingletonInstantiated();
 *      1、ioc容器创建：refresh()
 *      2、finshBeanFactoryInitialization(beanFactory); 初始化剩下的单实例bean
 *          1、先创建所有的单实例bean，getBean
 *          2、获取所有创建好的单实例bean，判断是否是SmartInitializingSingleton
 *              如果是就调用afterSingletonsInstantiated();
 */
@ComponentScan(value = "com.atguigu.ext")
@Configuration
public class ExtConfig {
    @Bean
    public Color color() {
        return new Color();
    }
}